package com.turing.post.cardmanagement.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.turing.post.cardmanagement.util.CardFace;
import com.turing.post.cardmanagement.util.CardFaceDao;
import com.turing.post.cardmanagement.util.MakeCardApproval;
import com.turing.post.cardmanagement.util.MakeCardApprovalDao;
import com.turing.post.cardmanagement.util.MakeCardControl;
import com.turing.post.cardmanagement.util.MakeCardControlBusiness;
import com.turing.post.cardmanagement.util.MakeCardControlDao;
import com.turing.post.cardmanagement.util.NonEntityCard;
import com.turing.post.cardmanagement.util.NonEntityCardDao;
import com.turing.post.common.util.PCPSCommonDao;
import com.turing.post.common.util.SysOperLog;
import com.turing.post.common.util.SysOperLogDao;
import com.turing.post.organization.util.IssueCompany;
import com.turing.post.organization.util.IssueCompanyDao;
import com.turing.post.report.util.BinaryFileInfo;
import com.turing.post.report.util.BinaryFileInfoDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;
import com.turing.post.util.PCPSWebInput;
import com.turing.post.util.SHA1;

/**
 * 卡审批主要业务逻辑实现
 * 
 * @author YangShuo
 * 
 */
@Stateless(mappedName = "cardmanagement.impl.MakeCardControlBusinessImpl")
@Remote
@Local
public class MakeCardControlBusinessImpl implements MakeCardControlBusiness {

	/**
	 * 实体管理器
	 * 
	 * @see javax.persistence.EntityManager
	 */
	@PersistenceContext
	protected EntityManager _em;

	@EJB(mappedName = "common.impl.PCPSCommonDaoImpl")
	private PCPSCommonDao PCPSCommonDaoImpl;

	@EJB(mappedName = "report.impl.BinaryFileInfoDaoImpl")
	private BinaryFileInfoDao binaryFileInfoDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.MakeCardApprovalDaoImpl")
	private MakeCardApprovalDao MakeCardApprovalDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.MakeCardControlDaoImpl")
	private MakeCardControlDao MakeCardControlDaoImpl;

	@EJB(mappedName = "organization.impl.IssueCompanyDaoImpl")
	private IssueCompanyDao issueCompanyDaoImpl;

	@EJB(mappedName = "common.impl.SysOperLogDaoImpl")
	private SysOperLogDao sysOperLogDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.CardFaceDaoImpl")
	private CardFaceDao cardFaceDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.NonEntityCardDaoImpl")
	private NonEntityCardDao NonEntityCardDaoImpl;

	/**
	 * 产生批次号方法
	 * 
	 * @param IssueCompanyNo
	 */
	// @Override
	private String getCreatBatchno(String issueCompanyNo)
			throws PCPSApplicationException {
		// 取得发卡商号码
		// String IssueCompanyNo = MakeCardApprovalDaoImpl
		// .getMakeCardApprovalByMakeCardApplyForId(MakeCardApplyForId)
		// .getIssueCompanyNo();
		// 构建sql取得当前发卡商最大批次号+1
		String sql = "select to_char(sysdate,'yy')||replace(to_char(nvl(max(to_number(SUBSTR(batchno,9,4))),0)+1,'0999'),' ','') "
				+ "from makecardcontrol where issuecompanyno=?1 and SUBSTR(batchno,7,2)=to_char(sysdate,'yy')";
		Query query = _em.createNativeQuery(sql);
		query.setParameter(1, issueCompanyNo);
		return (String) query.getSingleResult();
	}

	/**
	 * 检查已入库张数，不足将状态置为部分入库，否则置为制卡成功，已入库
	 */
	@Override
	public void checkAlreadyInStockCount(Integer count, String Batchno)
			throws PCPSApplicationException {
		// 用批次号取得制卡控制信息
		MakeCardControl mcc = MakeCardControlDaoImpl
				.getMakeCardControlByBatchNo(Batchno);
		mcc.setAlreadyInStockCount(mcc.getAlreadyInStockCount() + count);
		if (mcc.getAlreadyInStockCount().equals(mcc.getCardCount()))
			mcc.setStatus(MakeCardControl.STATUS_INSTOCK);
		else
			mcc.setStatus(MakeCardControl.STATUS_PARTIN);
		MakeCardControlDaoImpl.updateMakeCardControl(mcc);
	}

	/**
	 * 制卡方法
	 * 
	 * @param MakeCardApplyForId
	 */
	@Override
	public void makeCard(PCPSWebInput webInput, BigInteger makeCardApplyForId)
			throws PCPSApplicationException {

		// 根据MakeCardApplyForId得到制卡信息
		MakeCardApproval mca = MakeCardApprovalDaoImpl
				.getMakeCardApprovalByMakeCardApplyForId(makeCardApplyForId);
		if (!mca.getStatus().equals(MakeCardApproval.STATUS_FINANCEAUTH))
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"状态不是财务批准");
		// 发卡商号
		String issueCompanyNo = mca.getIssueCompanyNo();
		// 将申请表中记录改为已启动制卡。
		mca.setStatus(MakeCardApproval.STATUS_MAKED);
		MakeCardApprovalDaoImpl.updateMakeCardApproval(mca);

		// 卡图样
		CardFace cardFace = cardFaceDaoImpl.getCardFaceByCardFaceId(mca
				.getCardFaceId());
		// 生成制卡批次号
		String serBatch = getCreatBatchno(issueCompanyNo);
		String batchNo = issueCompanyNo + serBatch;

		// 判断是否为代发卡
		if (!PCPSUtil.isEmpty(mca.getProxyIssueBin())) {
			batchNo = mca.getProxyIssueBin() + serBatch;
		}

		// 用mca填充一个MakeCardControl
		MakeCardControl mcc = padding(mca, batchNo);
		mcc.setMediaType(cardFace.getMediaType());// 介质类型
		// 插入开始制卡信息
		MakeCardControlDaoImpl.insertMakeCardControl(mcc);
		// 产生制卡信息
		List<NonEntityCard> cardlist = creatMakeCardInfo(mcc, cardFace);
		// 产生Excel文件放入mcc中
		byte[] cardfile = createCardFile(cardlist, mcc);
		// byte[] cardfile=new byte[10];
		// mcc.setCardFileLength(cardfile.length);
		BigInteger cardFileContentId = binaryFileInfoDaoImpl
				.insertOrUpdateBinaryFile(cardfile, null, BinaryFileInfo.XLS);
		mcc.setCardFileContentId(cardFileContentId);
		// 将list中的明文密码转为密文密码
		cardlist = getSha1Pwd(cardlist);
		// 将cardlist中的数据插入数据库
		insertCardlist(cardlist);
		// 修改制卡控制状态为制卡成功待下载
		mcc.setStatus(MakeCardControl.STATUS_WAITDOWNLOAD);
		mcc.setEndTime(PCPSCommonDaoImpl.getDatabaseSysTime());
		MakeCardControlDaoImpl.updateMakeCardControl(mcc);

		// 日志记录
		sysOperLogDaoImpl.insertSysOperLogInfo(webInput,
				SysOperLog.operType_Add, "制卡", "BatchNo:" + mcc.getBatchNo());
	}

	/**
	 * 下载制卡文件方法
	 * 
	 * @param userid
	 * @param Batchno
	 */
	@Override
	public byte[] downFile(PCPSWebInput webInput, BigInteger userid,
			String BatchNo) throws PCPSApplicationException {
		// 根据batchno找到信息并判断userid是否是制卡人
		MakeCardControl mcc = MakeCardControlDaoImpl
				.getMakeCardControlByBatchNoForDownLoad(BatchNo);
		try {
			if (mcc.getOperNo().compareTo(userid) != 0) {
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "非本人提取卡文件，不允许");
			}
		} catch (Exception e) {
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"非本人提取卡文件，不允许");
		}
		if (!mcc.getStatus().equals(MakeCardControl.STATUS_WAITDOWNLOAD))
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"该文件已下载");

		// 如是制卡人就将制卡信息数组取出并删除数据库中的
		BinaryFileInfo fileInfo = binaryFileInfoDaoImpl
				.getBinaryFileInfoById(mcc.getCardFileContentId());
		if (fileInfo == null) {
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"制卡文件已经删除！");
		}
		byte[] cardfile = fileInfo.getFileContent();
		byte[] aResult = new byte[cardfile.length];
		System.arraycopy(cardfile, 0, aResult, 0, aResult.length);
		// 将数据库卡文件置为null以及修改status
		binaryFileInfoDaoImpl.deleteBinaryFileInfoById(mcc
				.getCardFileContentId());
		MakeCardControlDaoImpl.updateMakeCardControlForDownLoad(mcc
				.getBatchNo());
		// 日志记录
		sysOperLogDaoImpl.insertSysOperLogInfo(webInput,
				SysOperLog.operType_Add, "下载制卡文件", "BatchNo:" + BatchNo);
		// 返回byte数组
		return aResult;
	}

	private void insertCardlist(List<NonEntityCard> cardlist)
			throws PCPSApplicationException {
		PCPSUtil.Log("Start Insert NonEntityCard");
		for (int i = 0; i < cardlist.size(); i++) {
			NonEntityCardDaoImpl.insertNonEntityCard(cardlist.get(i));
		}
		PCPSUtil.Log("End Insert NonEntityCard");
	}

	private MakeCardControl padding(MakeCardApproval mca, String Batchno) {
		MakeCardControl mcc = new MakeCardControl();
		mcc.setBatchNo(Batchno);
		mcc.setReason(mca.getReason());
		mcc.setIssueCompanyNo(mca.getIssueCompanyNo());
		mcc.setIssueBranchNo(mca.getIssueBranchNo());
		mcc.setOperNo(mca.getOperId());
		mcc.setStartTime(PCPSCommonDaoImpl.getDatabaseSysTime());
		mcc.setCardManufactureId(mca.getCardManufactureId());
		mcc.setCardFaceId(mca.getCardFaceId());
		mcc.setProxyIssue(mca.getProxyIssueBin());
		mcc.setCardCount(mca.getCardCount());
		mcc.setExpired(mca.getExpired());
		mcc.setStatus(MakeCardControl.STATUS_MAKING);
		mcc.setAlreadyInStockCount(0);
		mcc.setExpiredAlgorithm(mca.getExpiredAlgorithm());
		mcc.setExpiredUnit(mca.getExpiredUnit());
		mcc.setHintInfo(mca.getHintInfo());
		IssueCompany ic = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(mca.getIssueCompanyNo());
		mcc.setOrderNumber(PCPSCommonDaoImpl.getOrderNumber(ic.getTranDate(),
				mca.getIssueBranchNo()));
		return mcc;
	}

	/**
	 * 产生制卡信息集合,返回装有NonEntityCard实体的list集合
	 */

	private List<NonEntityCard> creatMakeCardInfo(MakeCardControl mcc,
			CardFace cardFace) throws PCPSApplicationException {
		List<NonEntityCard> list = new ArrayList<NonEntityCard>();
		int i = 0;
		int count = mcc.getCardCount();
		BigInteger id = null;
		HashMap<String, String> hm = new HashMap<String, String>();
		do {
			id = new BigInteger(30, 10, (new Random(System.currentTimeMillis()
					+ i)));
			String sid = id.toString();
			sid = sid.substring(1, 8);
			boolean ishave = hm.containsValue(sid);
			if (!ishave) {
				hm.put(String.valueOf(i), sid);
				i++;
			}
		} while (i < count);
		for (int j = 0; j < hm.size(); j++) {
			NonEntityCard nec = new NonEntityCard();
			nec.setBatchNo((mcc.getBatchNo()));
			String seqno = String.valueOf(j + 1);
			while (seqno.length() < 6) {
				seqno = "0" + seqno;
			}
			nec.setCardSeqNo(mcc.getBatchNo() + seqno);
			nec.setCardNo(mcc.getBatchNo() + hm.get(String.valueOf(j)));
			// 随即8密码
			BigInteger myval = new BigInteger(seqno)
					.mod(BigInteger.valueOf(37)).add(BigInteger.ONE);
			Random r = new Random(System.currentTimeMillis() * myval.intValue());
			BigInteger bi = new BigInteger(50, 10, r);
			nec.setCardPwd(bi.toString().substring(1, 9));
			// nec.setCardPwd("00000000");
			// 如为磁卡，产生2磁道内容。否侧填卡号
			if (CardFace.CARDFACE_MEDIATYPE_CK.equals(cardFace.getMediaType()))
				nec.setTwoTrackContent(nec.getCardNo() + "=000029"
						+ getCVNByCardInfo(nec.getCardNo() + "0000029")
						+ "00000000");
			else
				nec.setTwoTrackContent(nec.getCardNo());
			nec.setThirdTrackContent(nec.getTwoTrackContent());
			list.add(nec);
		}
		return list;
	}

	/**
	 * 产生cvn校验码
	 */
	@Override
	public String getCVNByCardInfo(String cardnoinfo)
			throws PCPSApplicationException {
		long l = Long.parseLong(cardnoinfo.substring(1, 11)) % 999
				+ Long.parseLong(cardnoinfo.substring(11, 20)) % 999;
		if (l <= 99)
			l = l + 99;
		String s = String.valueOf(l);
		if (s.length() > 3)
			s = s.substring(1, 4);
		return s;
	}

	/**
	 * // * 产生制卡文件 //
	 */
	@SuppressWarnings("deprecation")
	private byte[] createCardFile(List<NonEntityCard> cardlist,
			MakeCardControl mcc) {
		PCPSUtil.Log("Start Create CardFile.xls");
		byte[] cardfile = null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet("制卡信息");
		HSSFRow row = sheet.createRow(0);
		String[] column = {
				"批次号：" + mcc.getBatchNo(),
				"卡图样："
						+ cardFaceDaoImpl.getCardFaceByCardFaceId(
								mcc.getCardFaceId()).getCardFaceName(),
				"制卡张数：" + mcc.getCardCount(), "", "" };
		for (short i = 0; i < 5; i++) {
			HSSFCell cell = row.createCell(i);
			cell.setCellValue(column[i]);
			if (i < 3) {
				sheet.setColumnWidth(i, 5800);// 设置列宽带
			} else {
				sheet.setColumnWidth(i, 10000);// 设置列宽带
			}
		}
		row = sheet.createRow(1);
		String[] secondcolumn = { "顺序号", "卡号", "密码", "二磁道内容", "三磁道内容" };
		for (short i = 0; i < 5; i++) {
			HSSFCell cell = row.createCell(i);
			cell.setCellValue(secondcolumn[i]);
		}
		for (int j = 0; j < cardlist.size(); j++) {
			NonEntityCard nec = (NonEntityCard) cardlist.get(j);
			row = sheet.createRow(j + 2);
			String[] rowcontext = { nec.getCardSeqNo(), nec.getCardNo(),
					nec.getCardPwd() + "", nec.getTwoTrackContent(),
					nec.getThirdTrackContent() };
			for (short i = 0; i < 5; i++) {
				HSSFCell cell = row.createCell(i);
				cell.setCellValue(rowcontext[i]);
			}
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			e.printStackTrace();
		}
		cardfile = out.toByteArray();
		PCPSUtil.Log("End Create CardFile.xls");
		return cardfile;
	}

	private List<NonEntityCard> getSha1Pwd(List<NonEntityCard> cardlist)
			throws PCPSApplicationException {
		for (int i = 0; i < cardlist.size(); i++) {
			cardlist.get(i)
					.setCardPwd(
							(new SHA1())
									.getDigestOfString((cardlist.get(i)
											.getCardNo() + cardlist.get(i)
											.getCardPwd()).getBytes()));
		}
		return cardlist;
	}
}
